The first function in this example uses the BOF and EOF properties to display a message if a user tries to move past the first or last record of a Recordset. It uses the Bookmark property to let the user flag a record in a Recordset and return to it later.
The second function uses the Bookmark property to place the Bookmark of every other record from a Recordset into an array, and then filters the Recordset using the array.
#import "C:\Program Files\Common Files\System\ADO\msado15.dll" \
no_namespace rename("EOF", "EndOfFile")
#include <ole2.h>
#include <stdio.h>
#include <conio.h>
#include "BofEofBookmark.h"
// Function declarations
inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);};
void BOFX(void);
void BookmarkX(void);
void PrintProviderError(_ConnectionPtr pConnection);
void PrintComError(_com_error &e);
///////////////////////////////////////////////////////////
// //
// BOFX Function //
// //
///////////////////////////////////////////////////////////
void main()
{
if(FAILED(::CoInitialize(NULL)))
return;
BOFX();
//Clear the screen for the next display
system("cls");
BookmarkX();
printf("Press any key to continue...");
getch();
::CoUninitialize();
}
///////////////////////////////////////////////////////////
// //
// BOFX Function //
// //
///////////////////////////////////////////////////////////
void BOFX(void)
{
// Define ADO object pointers.
// Initialize pointers on define.
// These are in the ADODB:: namespace
_RecordsetPtr rstPublishers = NULL;
//Define Other Variables
HRESULT hr = S_OK;
IADORecordBinding *picRs = NULL; //Interface Pointer declared.
CPublishers Publs;
bstr_t strCnn("Provider=sqloledb;Data Source=srv;"
"Initial Catalog=Pubs;User Id=sa;Password=;");
_bstr_t strMessage;
_variant_t VarBookmark;
int intCommand = 0;
_variant_t TempPublisher;
try
{
// Open recordset with data from Publishers table.
TESTHR(rstPublishers.CreateInstance(__uuidof(Recordset)));
rstPublishers->CursorType = adOpenStatic;
// Use client cursor to enable AbsolutePosition property.
rstPublishers->CursorLocation = adUseClient;
rstPublishers->Open("select pub_id, pub_name from publishers"
" order by pub_name", strCnn, adOpenStatic,
adLockBatchOptimistic, adCmdText);
//Open an IADORecordBinding interface pointer
//which will be used for Binding Recordset to a class
TESTHR(rstPublishers->QueryInterface(
__uuidof(IADORecordBinding), (LPVOID*)&picRs));
//Bind the Recordset to a C++ Class here
TESTHR(picRs->BindToRecordset(&Publs));
rstPublishers->MoveFirst();
while (true) // Continuous loop.
{
// Display information about the current record
// and get user input
printf("Publisher:%s \n Record %d of %d\n\n",
Publs.lP_pubnameStatus == adFldOK ?
Publs.m_szP_pubname : "<NULL>",
rstPublishers->AbsolutePosition,
rstPublishers->RecordCount);
printf("Enter command:\n ");
printf("[1 - next / 2 - previous /\n");
printf(" 3 - set bookmark / 4 - go to bookmark /\n");
printf(" 5 - quit ]\n");
scanf("%d", &intCommand);
if ((intCommand < 1) || (intCommand > 4))
break; // Out of range entry exits program loop.
switch(intCommand)
{
// Move forward or backward, trapping for BOF or EOF
case 1:
rstPublishers->MoveNext();
if (rstPublishers->EndOfFile)
{
printf("\nCannot move past the last record."
" Try again...\n");
rstPublishers->MoveLast();
}
break;
case 2:
rstPublishers->MovePrevious();
if (rstPublishers->BOF)
{
printf("\nCannot move before the first record."
" Try again...\n");
rstPublishers->MoveFirst();
}
break;
// store the bookmark of the current record.
case 3:
VarBookmark = rstPublishers->Bookmark;
// Go to the record indicated by the
// stored bookmark
break;
case 4:
// Check for whether bookmark set for a record
if (VarBookmark.vt == VT_EMPTY)
printf("No Bookmark set!\n");
else
rstPublishers->Bookmark = VarBookmark;
break;
default:
break;
}
}
// Clean up objects before exit.
rstPublishers->Close();
//Release the IADORecordset Interface here
if (picRs)
picRs->Release();
}
catch (_com_error &e)
{
printf("Error in BOFx...\n");
// Notify the user of errors if any.
_variant_t vtConnect = rstPublishers->GetActiveConnection();
// GetActiveConnection returns connect string if connection
// is not open, else returns Connection object.
switch(vtConnect.vt)
{
case VT_BSTR:
printf("Error:\n");
printf("Code = %08lx\n", e.Error());
printf("Message = %s\n", e.ErrorMessage());
printf("Source = %s\n", (LPCSTR) e.Source());
printf("Description = %s\n", (LPCSTR) e.Description());
break;
case VT_DISPATCH:
PrintProviderError(vtConnect);
break;
default:
printf("Errors occured.");
break;
}
printf("Press any key to continue...");
getch();
}
}
///////////////////////////////////////////////////////////
// //
// BookmarkX Function //
// //
///////////////////////////////////////////////////////////
void BookmarkX(void)
{
// Define ADO object pointers.
// Initialize pointers on define.
// These are in the ADODB:: namespace.
_RecordsetPtr rstAuthors = NULL;
//Define Other Variables
IADORecordBinding *picRs = NULL; //Interface Pointer declared.
CAuthors Authrs;
HRESULT hr = S_OK;
_bstr_t strCnn("Provider=sqloledb;Data Source=srv;"
"Initial Catalog=Pubs;User Id=sa;Password=;");
_variant_t vBookmark;
// Variable declaration for safe arrays.
SAFEARRAY FAR* psa;
// define ARRAY/ VARIANT variant.
vBookmark.vt = VT_ARRAY|VT_VARIANT;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = 11;
long ii = 0;
try
{
rstAuthors.CreateInstance(__uuidof(Recordset));
// Set The Cursor Location
rstAuthors->CursorLocation = adUseClient;
rstAuthors->PutActiveConnection((_variant_t)strCnn);
// Open Authors table
TESTHR(rstAuthors->Open("select * from Authors",strCnn,
adOpenStatic,adLockBatchOptimistic,adCmdText));
//Open an IADORecordBinding interface pointer
//which we'll use for binding Recordset to a class
TESTHR(rstAuthors->QueryInterface(__uuidof(IADORecordBinding),
(LPVOID*)&picRs));
//Bind the Recordset to a C++ Class here
TESTHR(picRs->BindToRecordset(&Authrs));
printf("Number of Records before filtering: %d\n",
rstAuthors->RecordCount);
// Create safearrays to store array of variant
psa = SafeArrayCreate(VT_VARIANT,1,rgsabound);
// Store bookmark of every other record into an array.
while ((!rstAuthors->EndOfFile) && (ii < 11))
{
SafeArrayPutElement(psa,&ii,&rstAuthors->Bookmark);
//ii = ii +1;
ii++;
rstAuthors->Move(2);
}
vBookmark.parray = psa;
// Filter the Record with the array of bookmarks.
rstAuthors->put_Filter(vBookmark);
printf("Number of Records after filtering: %d\n",
rstAuthors->RecordCount);
rstAuthors->MoveFirst();
while (!rstAuthors->EndOfFile)
{
printf("%d %s\n",rstAuthors->AbsolutePosition,
Authrs.lau_lnameStatus == adFldOK ?
Authrs.m_szau_lname : "<NULL>");
rstAuthors->MoveNext();
}
//Release the IADORecordset Interface.
if (picRs)
picRs->Release();
// Clean up objects before exit.
rstAuthors->Close();
}
catch (_com_error &e)
{
// Notify the user of errors if any.
_variant_t vtConnect = rstAuthors->GetActiveConnection();
// GetActiveConnection returns connect string if connection
// is not open, else returns Connection object.
switch(vtConnect.vt)
{
case VT_BSTR:
printf("Error:\n");
printf("Code = %08lx\n", e.Error());
printf("Message = %s\n", e.ErrorMessage());
printf("Source = %s\n", (LPCSTR) e.Source());
printf("Description = %s\n", (LPCSTR) e.Description());
break;
case VT_DISPATCH:
PrintProviderError(vtConnect);
break;
default:
printf("Errors occured.");
break;
}
}
}
///////////////////////////////////////////////////////////
// //
// PrintProviderError Function //
// //
///////////////////////////////////////////////////////////
void PrintProviderError(_ConnectionPtr pConnection)
{
// Print Provider Errors from Connection object.
// pErr is a record object in the Connection's Error collection.
ErrorPtr pErr = NULL;
long nCount = 0;
long i = 0;
if( (pConnection->Errors->Count) > 0)
{
nCount = pConnection->Errors->Count;
// Collection ranges from 0 to nCount -1.
for(i = 0; i < nCount; i++)
{
pErr = pConnection->Errors->GetItem(i);
printf("Error number: %x\t%s\n", pErr->Number,
(LPCSTR) pErr->Description);
}
}
}
BofEofBookmark.h:
#include "icrsint.h"
//This Class extracts only pubid,lastname and hire_date
class CPublishers : public CADORecordBinding
{
BEGIN_ADO_BINDING(CPublishers)
//Column title is the 2nd field in the recordset
ADO_VARIABLE_LENGTH_ENTRY2(1, adVarChar, m_szP_pubid,
sizeof(m_szP_pubid), lP_pubidStatus, FALSE)
//Column type is the 3rd field in the recordset
ADO_VARIABLE_LENGTH_ENTRY2(2, adVarChar, m_szP_pubname,
sizeof(m_szP_pubname), lP_pubnameStatus, TRUE)
END_ADO_BINDING()
public:
CHAR m_szP_pubid;
ULONG lP_pubidStatus;
CHAR m_szP_pubname[40];
ULONG lP_pubnameStatus;
};
//This Class extracts only authorlastname
class CAuthors : public CADORecordBinding
{
BEGIN_ADO_BINDING(CAuthors)
//Column authorlname is the 2nd field in the recordset
ADO_VARIABLE_LENGTH_ENTRY2(2, adVarChar, m_szau_lname,
sizeof(m_szau_lname), lau_lnameStatus, FALSE)
END_ADO_BINDING()
public:
CHAR m_szau_lname[40];
ULONG lau_lnameStatus;
};